﻿using System;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;

public class USPropertyInfo : ScriptableObject
{
    private FieldInfo cachedFieldInfo;
    private PropertyInfo cachedPropertyInfo;
    public Component component;
    public List<USInternalCurve> curves = new List<USInternalCurve>();
    [Obsolete("curves0 - curves 4 is now Obsolete, please use the curves list, instead.")]
    public AnimationCurve curves0;
    [Obsolete("curves0 - curves 4 is now Obsolete, please use the curves list, instead.")]
    public AnimationCurve curves1;
    [Obsolete("curves0 - curves 4 is now Obsolete, please use the curves list, instead.")]
    public AnimationCurve curves2;
    [Obsolete("curves0 - curves 4 is now Obsolete, please use the curves list, instead.")]
    public AnimationCurve curves3;
    public string fieldName;
    public string propertyName;
    [SerializeField]
    private PropertyTypeInfo propertyType = PropertyTypeInfo.None;
    private Color tmpColour = Color.black;
    private Keyframe tmpKeyframe = new Keyframe();
    private Quaternion tmpQuat = Quaternion.identity;
    private Vector2 tmpVector2 = Vector2.zero;
    private Vector3 tmpVector3 = Vector3.zero;
    private Vector4 tmpVector4 = Vector4.zero;

    private void AddKeyframe(bool ourValue, float time, bool autoSmooth)
    {
        float num = 0f;
        if (ourValue)
        {
            num = 1f;
        }
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = num;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(double ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = (float) ourValue;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(int ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(long ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
    }

    public void AddKeyframe(object ourValue, float time, bool autoSmooth)
    {
        if (this.propertyType == PropertyTypeInfo.None)
        {
            Debug.LogError("Atempting to Add A Keyframe, before calling CreatePropertyInfo");
        }
        else if (GetMappedType(ourValue.GetType()) != this.propertyType)
        {
            Debug.LogError("Trying to Add a Keyframe of the wrong type");
        }
        else
        {
            switch (GetMappedType(ourValue.GetType()))
            {
                case PropertyTypeInfo.Int:
                    this.AddKeyframe((int) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Long:
                    this.AddKeyframe((long) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Float:
                    this.AddKeyframe((float) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Double:
                    this.AddKeyframe((double) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Bool:
                    this.AddKeyframe((bool) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Vec2:
                    this.AddKeyframe((Vector2) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Vec3:
                    this.AddKeyframe((Vector3) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Vec4:
                    this.AddKeyframe((Vector4) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Quat:
                    this.AddKeyframe((Quaternion) ourValue, time, autoSmooth);
                    break;

                case PropertyTypeInfo.Colour:
                    this.AddKeyframe((Color) ourValue, time, autoSmooth);
                    break;
            }
        }
    }

    private void AddKeyframe(float ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(Color ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.r;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.g;
        this.AddKeyframe(this.curves[1], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.b;
        this.AddKeyframe(this.curves[2], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.a;
        this.AddKeyframe(this.curves[3], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(Quaternion ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.x;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.y;
        this.AddKeyframe(this.curves[1], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.z;
        this.AddKeyframe(this.curves[2], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.w;
        this.AddKeyframe(this.curves[3], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(Vector2 ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.x;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.y;
        this.AddKeyframe(this.curves[1], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(Vector3 ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.x;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.y;
        this.AddKeyframe(this.curves[1], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.z;
        this.AddKeyframe(this.curves[2], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(Vector4 ourValue, float time, bool autoSmooth)
    {
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.x;
        this.AddKeyframe(this.curves[0], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.y;
        this.AddKeyframe(this.curves[1], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.z;
        this.AddKeyframe(this.curves[2], this.tmpKeyframe, autoSmooth);
        this.tmpKeyframe.time = time;
        this.tmpKeyframe.value = ourValue.w;
        this.AddKeyframe(this.curves[3], this.tmpKeyframe, autoSmooth);
    }

    private void AddKeyframe(USInternalCurve curve, Keyframe keyframe, bool autoSmooth)
    {
        USInternalKeyframe keyframe2 = curve.AddKeyframe(keyframe.time, keyframe.value);
        if (autoSmooth)
        {
            keyframe2.Smooth();
        }
        this.SetValue(keyframe.time);
    }

    private void CreatePropertyCurves()
    {
        switch (this.propertyType)
        {
            case PropertyTypeInfo.Int:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Long:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Float:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Double:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Bool:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Vec2:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                this.curves[1].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Vec3:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                this.curves[1].UnityAnimationCurve = new AnimationCurve();
                this.curves[2].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Vec4:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                this.curves[1].UnityAnimationCurve = new AnimationCurve();
                this.curves[2].UnityAnimationCurve = new AnimationCurve();
                this.curves[3].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Quat:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                this.curves[1].UnityAnimationCurve = new AnimationCurve();
                this.curves[2].UnityAnimationCurve = new AnimationCurve();
                this.curves[3].UnityAnimationCurve = new AnimationCurve();
                break;

            case PropertyTypeInfo.Colour:
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves.Add(ScriptableObject.CreateInstance<USInternalCurve>());
                this.curves[0].UnityAnimationCurve = new AnimationCurve();
                this.curves[1].UnityAnimationCurve = new AnimationCurve();
                this.curves[2].UnityAnimationCurve = new AnimationCurve();
                this.curves[3].UnityAnimationCurve = new AnimationCurve();
                break;
        }
    }

    public void CreatePropertyInfo(PropertyTypeInfo createdPropertyType)
    {
        if (this.propertyType != PropertyTypeInfo.None)
        {
            Debug.LogError("We are trying to CreatePropertyInfo, but it will be an overwrite!");
        }
        else
        {
            this.propertyType = createdPropertyType;
            this.CreatePropertyCurves();
        }
    }

    public static System.Type GetMappedType(PropertyTypeInfo type)
    {
        if (type == PropertyTypeInfo.Int)
        {
            return typeof(int);
        }
        if (type == PropertyTypeInfo.Long)
        {
            return typeof(long);
        }
        if (type == PropertyTypeInfo.Float)
        {
            return typeof(float);
        }
        if (type == PropertyTypeInfo.Double)
        {
            return typeof(double);
        }
        if (type == PropertyTypeInfo.Bool)
        {
            return typeof(bool);
        }
        if (type == PropertyTypeInfo.Vec2)
        {
            return typeof(Vector2);
        }
        if (type == PropertyTypeInfo.Vec3)
        {
            return typeof(Vector3);
        }
        if (type == PropertyTypeInfo.Vec4)
        {
            return typeof(Vector4);
        }
        if (type == PropertyTypeInfo.Quat)
        {
            return typeof(Quaternion);
        }
        if (type == PropertyTypeInfo.Colour)
        {
            return typeof(Color);
        }
        return null;
    }

    public static PropertyTypeInfo GetMappedType(System.Type type)
    {
        if (type == typeof(int))
        {
            return PropertyTypeInfo.Int;
        }
        if (type == typeof(long))
        {
            return PropertyTypeInfo.Long;
        }
        if ((type == typeof(float)) || (type == typeof(float)))
        {
            return PropertyTypeInfo.Float;
        }
        if (type == typeof(double))
        {
            return PropertyTypeInfo.Double;
        }
        if (type == typeof(bool))
        {
            return PropertyTypeInfo.Bool;
        }
        if (type == typeof(Vector2))
        {
            return PropertyTypeInfo.Vec2;
        }
        if (type == typeof(Vector3))
        {
            return PropertyTypeInfo.Vec3;
        }
        if (type == typeof(Vector4))
        {
            return PropertyTypeInfo.Vec4;
        }
        if (type == typeof(Quaternion))
        {
            return PropertyTypeInfo.Quat;
        }
        if (type == typeof(Color))
        {
            return PropertyTypeInfo.Colour;
        }
        return PropertyTypeInfo.None;
    }

    public object GetValueForTime(float time)
    {
        object tmpQuat = null;
        switch (this.propertyType)
        {
            case PropertyTypeInfo.Int:
                tmpQuat = this.curves[0].Evaluate(time);
                break;

            case PropertyTypeInfo.Long:
                tmpQuat = this.curves[0].Evaluate(time);
                break;

            case PropertyTypeInfo.Float:
                tmpQuat = this.curves[0].Evaluate(time);
                break;

            case PropertyTypeInfo.Double:
                tmpQuat = this.curves[0].Evaluate(time);
                break;

            case PropertyTypeInfo.Bool:
                tmpQuat = this.curves[0].Evaluate(time);
                break;

            case PropertyTypeInfo.Vec2:
                this.tmpVector2.x = this.curves[0].Evaluate(time);
                this.tmpVector2.y = this.curves[1].Evaluate(time);
                tmpQuat = this.tmpVector2;
                break;

            case PropertyTypeInfo.Vec3:
                this.tmpVector3.x = this.curves[0].Evaluate(time);
                this.tmpVector3.y = this.curves[1].Evaluate(time);
                this.tmpVector3.z = this.curves[2].Evaluate(time);
                tmpQuat = this.tmpVector3;
                break;

            case PropertyTypeInfo.Vec4:
                this.tmpVector4.x = this.curves[0].Evaluate(time);
                this.tmpVector4.y = this.curves[1].Evaluate(time);
                this.tmpVector4.z = this.curves[2].Evaluate(time);
                this.tmpVector4.w = this.curves[3].Evaluate(time);
                tmpQuat = this.tmpVector4;
                break;

            case PropertyTypeInfo.Quat:
                this.tmpQuat.x = this.curves[0].Evaluate(time);
                this.tmpQuat.y = this.curves[1].Evaluate(time);
                this.tmpQuat.z = this.curves[2].Evaluate(time);
                this.tmpQuat.w = this.curves[3].Evaluate(time);
                tmpQuat = this.tmpQuat;
                break;

            case PropertyTypeInfo.Colour:
                this.tmpColour.r = this.curves[0].Evaluate(time);
                this.tmpColour.g = this.curves[1].Evaluate(time);
                this.tmpColour.b = this.curves[2].Evaluate(time);
                this.tmpColour.a = this.curves[3].Evaluate(time);
                tmpQuat = this.tmpColour;
                break;
        }
        if (tmpQuat == null)
        {
            return null;
        }
        return tmpQuat;
    }

    public bool HasPropertyBeenModified(float runningTime)
    {
        if (this.component != null)
        {
            object obj2 = null;
            if (this.fieldInfo != null)
            {
                obj2 = this.fieldInfo.GetValue(this.component);
            }
            if (this.propertyInfo != null)
            {
                obj2 = this.propertyInfo.GetValue(this.component, null);
            }
            object valueForTime = this.GetValueForTime(runningTime);
            if ((obj2 == null) || (valueForTime == null))
            {
                return false;
            }
            if (obj2.GetType() != valueForTime.GetType())
            {
                return false;
            }
            switch (this.propertyType)
            {
                case PropertyTypeInfo.Int:
                    return (((int) obj2) != ((int) valueForTime));

                case PropertyTypeInfo.Long:
                    return (((long) obj2) != ((long) valueForTime));

                case PropertyTypeInfo.Float:
                    return !Mathf.Approximately((float) obj2, (float) valueForTime);

                case PropertyTypeInfo.Double:
                    return !Mathf.Approximately((float) obj2, (float) valueForTime);

                case PropertyTypeInfo.Bool:
                    return (((bool) obj2) != ((bool) valueForTime));

                case PropertyTypeInfo.Vec2:
                {
                    this.tmpVector2 = (Vector2) obj2;
                    Vector2 vector = (Vector2) valueForTime;
                    return (this.tmpVector2 != vector);
                }
                case PropertyTypeInfo.Vec3:
                {
                    this.tmpVector3 = (Vector3) obj2;
                    Vector3 vector2 = (Vector3) valueForTime;
                    return (this.tmpVector3 != vector2);
                }
                case PropertyTypeInfo.Vec4:
                {
                    this.tmpVector4 = (Vector4) obj2;
                    Vector4 vector3 = (Vector4) valueForTime;
                    return (this.tmpVector4 != vector3);
                }
                case PropertyTypeInfo.Quat:
                {
                    this.tmpQuat = (Quaternion) obj2;
                    Quaternion quaternion = (Quaternion) valueForTime;
                    bool flag = Mathf.Abs((float) (quaternion.eulerAngles.x - this.tmpQuat.eulerAngles.x)) > 0.05f;
                    bool flag2 = Mathf.Abs((float) (quaternion.eulerAngles.y - this.tmpQuat.eulerAngles.y)) > 0.05f;
                    bool flag3 = Mathf.Abs((float) (quaternion.eulerAngles.z - this.tmpQuat.eulerAngles.z)) > 0.05f;
                    return ((flag || flag2) || flag3);
                }
                case PropertyTypeInfo.Colour:
                {
                    this.tmpColour = (Color) obj2;
                    Color color = (Color) valueForTime;
                    return (this.tmpColour != color);
                }
            }
        }
        return false;
    }

    public void SetValue(float time)
    {
        if (this.curves.Count != 0)
        {
            if (this.propertyType == PropertyTypeInfo.None)
            {
                Debug.LogError("Atempting to Set A Value, before calling CreatePropertyInfo");
            }
            else
            {
                object tmpQuat = null;
                switch (this.propertyType)
                {
                    case PropertyTypeInfo.Int:
                        tmpQuat = this.curves[0].Evaluate(time);
                        break;

                    case PropertyTypeInfo.Long:
                        tmpQuat = this.curves[0].Evaluate(time);
                        break;

                    case PropertyTypeInfo.Float:
                        tmpQuat = this.curves[0].Evaluate(time);
                        break;

                    case PropertyTypeInfo.Double:
                        tmpQuat = this.curves[0].Evaluate(time);
                        break;

                    case PropertyTypeInfo.Bool:
                        tmpQuat = this.curves[0].Evaluate(time);
                        break;

                    case PropertyTypeInfo.Vec2:
                        this.tmpVector2.x = this.curves[0].Evaluate(time);
                        this.tmpVector2.y = this.curves[1].Evaluate(time);
                        tmpQuat = this.tmpVector2;
                        break;

                    case PropertyTypeInfo.Vec3:
                        this.tmpVector3.x = this.curves[0].Evaluate(time);
                        this.tmpVector3.y = this.curves[1].Evaluate(time);
                        this.tmpVector3.z = this.curves[2].Evaluate(time);
                        tmpQuat = this.tmpVector3;
                        break;

                    case PropertyTypeInfo.Vec4:
                        this.tmpVector4.x = this.curves[0].Evaluate(time);
                        this.tmpVector4.y = this.curves[1].Evaluate(time);
                        this.tmpVector4.z = this.curves[2].Evaluate(time);
                        this.tmpVector4.w = this.curves[3].Evaluate(time);
                        tmpQuat = this.tmpVector4;
                        break;

                    case PropertyTypeInfo.Quat:
                        this.tmpQuat.x = this.curves[0].Evaluate(time);
                        this.tmpQuat.y = this.curves[1].Evaluate(time);
                        this.tmpQuat.z = this.curves[2].Evaluate(time);
                        this.tmpQuat.w = this.curves[3].Evaluate(time);
                        tmpQuat = this.tmpQuat;
                        break;

                    case PropertyTypeInfo.Colour:
                        this.tmpColour.r = this.curves[0].Evaluate(time);
                        this.tmpColour.g = this.curves[1].Evaluate(time);
                        this.tmpColour.b = this.curves[2].Evaluate(time);
                        this.tmpColour.a = this.curves[3].Evaluate(time);
                        tmpQuat = this.tmpColour;
                        break;
                }
                if (tmpQuat != null)
                {
                    if (this.fieldInfo != null)
                    {
                        this.fieldInfo.SetValue(this.component, tmpQuat);
                    }
                    if (this.propertyInfo != null)
                    {
                        this.propertyInfo.SetValue(this.component, tmpQuat, null);
                    }
                }
            }
        }
    }

    public FieldInfo fieldInfo
    {
        get
        {
            if (this.cachedFieldInfo == null)
            {
                if ((this.component == null) || (this.fieldName == null))
                {
                    return null;
                }
                this.cachedFieldInfo = this.component.GetType().GetField(this.fieldName);
            }
            return this.cachedFieldInfo;
        }
        set
        {
            if (value != null)
            {
                this.fieldName = value.Name;
            }
            else
            {
                this.fieldName = null;
            }
            this.cachedFieldInfo = value;
        }
    }

    public PropertyInfo propertyInfo
    {
        get
        {
            if (this.cachedPropertyInfo == null)
            {
                if ((this.component == null) || (this.propertyName == null))
                {
                    return null;
                }
                this.cachedPropertyInfo = this.component.GetType().GetProperty(this.propertyName);
            }
            return this.cachedPropertyInfo;
        }
        set
        {
            if (value != null)
            {
                this.propertyName = value.Name;
            }
            else
            {
                this.propertyName = null;
            }
            this.cachedPropertyInfo = value;
        }
    }
}

